package tech.wetech.admin.web.dto.system;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.config.ColumnOverride;
import org.mybatis.generator.config.IgnoredColumn;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * 生成器传输类
 * <p>
 * Created by cjbi on 2018/1/14.
 */
public class GeneratorDto{

    /**
     * 代码生成根目录（必须为绝对路径）
     * <p>
     * 示例值：/opt/dev/myproject
     * <p>
     * 默认会在此目录下创建模块子目录
     */
    @NotNull(message = "项目文件夹不能为空")
    private String projectFolder;

    /**
     * 模块名称
     * <p>
     * 将在项目根目录下创建对应名称的子目录
     * 示例值：usermgmt
     */
    @NotNull(message = "模块名称不能为空")
    private String moduleName;

    /**
     * 模型类包路径
     * <p>
     * 默认生成路径：src/main/java/com/example/user/model
     */
    @NotNull(message = "Model包名不能为空")
    private String modelPackage;

    /**
     * Model类目标目录（相对路径）
     * <p>
     * 默认值：src/main/java
     */
    private String modelPackageTargetFolder;

    /**
     * DAO接口包路径
     * <p>
     * 默认生成路径：src/main/java/com/example/user/dao
     */
    @NotNull(message = "DAO包名不能为空")
    private String daoPackage;

    /**
     * DAO接口目标目录
     * <p>
     * 指定生成的DAO接口文件存放路径（默认在src/main/java目录下）
     * <p>
     * 示例值："com/example/user/dao"
     * <p>
     * 路径规则：
     * 1. 使用点号分隔包层级
     * 2. 会自动创建不存在的目录结构
     * 3. 默认值：src/main/java
     */
    private String daoTargetFolder;

    /**
     * MyBatis Mapper接口名称
     * <p>
     * 生成的Mapper接口类名（需符合Java接口命名规范）
     * <p>
     * 示例值："SysUserMapper"
     * <p>
     * 命名建议：
     * - 使用"Mapper"作为后缀
     * - 与数据库表名对应（如：sys_user → SysUserMapper）
     */
    private String mapperName;

    /**
     * MyBatis映射文件包路径
     * <p>
     * XML映射文件的包路径（不包含src/main/resources前缀）
     * <p>
     * 示例值："mapper"
     * <p>
     * 实际路径 = resources目录 + 该值
     * <p>
     * 路径规则：
     * 1. 使用点号分隔包层级
     * 2. 默认会创建resources/mapper目录
     */
    @NotNull
    private String mappingXMLPackage;


    /**
     * MyBatis映射文件目标目录
     * <p>
     * XML映射文件生成目录（相对于resources目录）
     * <p>
     * 示例值："mybatis/mappers"
     * <p>
     * 实际路径 = src/main/resources/mybatis/mappers/
     * <p>
     * 路径规则：
     * 1. 必须以斜杠结尾
     * 2. 支持多级目录
     */
    @NotNull
    private String mappingXMLTargetFolder;

    /**
     * 数据库表名
     * <p>
     * 需要生成代码的目标表名称（区分大小写）
     * <p>
     * 示例值："sys_user"
     * <p>
     * 命名规范：
     * - 必须使用下划线分隔（数据库标准）
     * - 不能包含特殊字符
     * - 长度不超过64字符
     */
    @NotNull
    private String tableName;

    @NotNull
    private String modelName;

    /**
     * 是否启用分页功能
     * <p>
     * 当设置为true时，会在生成的Example类中添加分页参数
     */
    private boolean offsetLimit;

    /**
     * 是否生成字段注释
     * <p>
     * 从数据库表字段注释中提取生成JavaDoc注释
     */
    private boolean comment;

    /**
     * 是否生成toString/hashCode/equals方法
     * <p>
     * 使用Apache Commons Lang的ToStringBuilder实现
     */
    private boolean needToStringHashcodeEquals;

    /**
     * 是否使用Lombok注解
     * <p>
     * 当启用时，会自动添加@Data和@Builder注解
     */
    private boolean annotation;

    /**
     * 是否使用数据库列的实际名称
     * <p>
     * 当设置为false时，会使用驼峰命名转换
     */
    private boolean useActualColumnNames;

    /**
     * 生成主键策略配置
     * <p>
     * 决定是否生成主键生成策略（如自增ID、UUID等）
     * 示例值："auto_increment" 或 "uuid"
     */
    private String generateKeys;

    /**
     * 是否使用表名作为实体类别名
     * <p>
     * true：在生成的SQL中使用表名作为别名（例如：FROM sys_user u）
     * false：使用实体类名作为别名（例如：FROM SysUser u）
     */
    private boolean useTableNameAlias;

    /**
     * Service实现类名称
     * <p>
     * 示例值："UserServiceImpl"
     * <p>
     * 必须符合Java类命名规范
     */
    @NotNull
    private String serviceImplName;

    /**
     * Service实现类包路径
     * <p>
     * 默认生成路径：src/main/java/com/example/user/service/impl
     */
    @NotNull
    private String serviceImplPackage;

    /**
     * Service实现类目标目录（相对路径）
     * <p>
     * 默认值：src/main/java
     * <p>
     * 实际路径 = 基础路径 + 该值
     */
    private String serviceImplTargetFolder;

    /**
     * Service接口名称
     * <p>
     * 示例值："UserService"
     * <p>
     * 必须符合Java接口命名规范
     */
    @NotNull
    private String serviceName;

    /**
     * Service接口包路径
     * <p>
     * 默认生成路径：src/main/java/com/example/user/service
     */
    @NotNull
    private String servicePackage;

    /**
     * Service接口目标目录（相对路径）
     * <p>
     * 默认值：src/main/java
     * <p>
     * 实际路径 = 基础路径 + 该值
     */
    private String serviceTargetFolder;

    /**
     * Controller类名称
     * <p>
     * 示例值："UserController"
     * <p>
     * 必须符合Java类命名规范
     */
    /*@NotNull*/
    private String controllerName;

    /**
     * Controller类包路径
     * <p>
     * 默认生成路径：src/main/java/com/example/user/controller
     */
    @NotNull
    private String controllerPackage;

    /**
     * Controller类目标目录（相对路径）
     * <p>
     * 默认值：src/main/java
     * <p>
     * 实际路径 = 基础路径 + 该值
     */
    private String controllerTargetFolder;

    /**
     * JSP视图文件名称
     * <p>
     * 示例值："user_list"
     * <p>
     *
     * */
    private String jspName;

    /**
     * JSP视图文件目标目录
     * <p>
     * 指定生成的JSP文件存放路径（自动添加WEB-INF前缀）
     * <p>
     * 示例值："user" → 实际路径：src/main/webapp/WEB-INF/jsp/user/
     * <p>
     * 路径规则：
     * 1. 不需要包含WEB-INF前缀（会自动添加）
     * 2. 只能包含字母、数字、下划线和短横线
     * 3. 必须以斜杠结尾（自动补全）
     * <p>
     * 特殊处理：
     * - 当设置为空值时，默认使用"main_page"
     * - 非法字符会被自动替换为下划线
     */
    @NotNull
    private String jspTargetFolder;

    /**
     * 要忽略的行
     */
    private List<IgnoredColumn> ignoredColumns;

    /**
     * 重写的行
     */
    private List<ColumnOverride> columnOverrides;

    public List<IgnoredColumn> getIgnoredColumns() {
        return ignoredColumns;
    }

    public void setIgnoredColumns(List<IgnoredColumn> ignoredColumns) {
        this.ignoredColumns = ignoredColumns;
    }

    public List<ColumnOverride> getColumnOverrides() {
        return columnOverrides;
    }

    public void setColumnOverrides(List<ColumnOverride> columnOverrides) {
        // 校验每个ColumnOverride对象
        /*if (columnOverrides != null) {
            columnOverrides.forEach(override -> {
                if (StringUtils.isBlank(override.getColumnName())) {
                    throw new IllegalArgumentException("Column name is required for columnOverride");
                }
                if (StringUtils.isBlank(override.getProperty(override.getColumnName()))) {
                    throw new IllegalArgumentException("Property name is required for columnOverride");
                }
            });
        }*/
        this.columnOverrides = columnOverrides;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getServicePackage() {
        return servicePackage;
    }

    public void setServicePackage(String servicePackage) {
        this.servicePackage = servicePackage;
    }

    public String getControllerName() {
        return controllerName;
    }

    public void setControllerName(String controllerName) {
        this.controllerName = controllerName;
    }

    public String getControllerPackage() {
        return controllerPackage;
    }

    public void setControllerPackage(String controllerPackage) {
        this.controllerPackage = controllerPackage;
    }

    public String getJspName() {
        return jspName;
    }

    public void setJspName(String jspName) {
        this.jspName = jspName;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getModelName() {
        return modelName;
    }

    public void setModelName(String modelName) {
        this.modelName = modelName;
    }

    public String getProjectFolder() {
        return projectFolder;
    }

    public void setProjectFolder(String projectFolder) {
        this.projectFolder = projectFolder;
    }

    public String getModelPackage() {
        return modelPackage;
    }

    public void setModelPackage(String modelPackage) {
        this.modelPackage = modelPackage;
    }

    public String getModelPackageTargetFolder() {
        return modelPackageTargetFolder;
    }

    public void setModelPackageTargetFolder(String modelPackageTargetFolder) {
        this.modelPackageTargetFolder = modelPackageTargetFolder;
    }

    public String getDaoPackage() {
        return daoPackage;
    }

    public void setDaoPackage(String daoPackage) {
        this.daoPackage = daoPackage;
    }

    public String getDaoTargetFolder() {
        return daoTargetFolder;
    }

    public void setDaoTargetFolder(String daoTargetFolder) {
        this.daoTargetFolder = daoTargetFolder;
    }

    public String getMappingXMLPackage() {
        return mappingXMLPackage;
    }

    public void setMappingXMLPackage(String mappingXMLPackage) {
        this.mappingXMLPackage = mappingXMLPackage;
    }

    public String getMappingXMLTargetFolder() {
        return mappingXMLTargetFolder;
    }

    public void setMappingXMLTargetFolder(String mappingXMLTargetFolder) {
        this.mappingXMLTargetFolder = mappingXMLTargetFolder;
    }

    public boolean isOffsetLimit() {
        return offsetLimit;
    }

    public void setOffsetLimit(boolean offsetLimit) {
        this.offsetLimit = offsetLimit;
    }

    public boolean isComment() {
        return comment;
    }

    public void setComment(boolean comment) {
        this.comment = comment;
    }

    public boolean isNeedToStringHashcodeEquals() {
        return needToStringHashcodeEquals;
    }

    public void setNeedToStringHashcodeEquals(boolean needToStringHashcodeEquals) {
        this.needToStringHashcodeEquals = needToStringHashcodeEquals;
    }

    public boolean isAnnotation() {
        return annotation;
    }

    public void setAnnotation(boolean annotation) {
        this.annotation = annotation;
    }

    public boolean isUseActualColumnNames() {
        return useActualColumnNames;
    }

    public void setUseActualColumnNames(boolean useActualColumnNames) {
        this.useActualColumnNames = useActualColumnNames;
    }

    public String getMapperName() {
        return mapperName;
    }

    public void setMapperName(String mapperName) {
        this.mapperName = mapperName;
    }

    public String getGenerateKeys() {
        return generateKeys;
    }

    public void setGenerateKeys(String generateKeys) {
        this.generateKeys = generateKeys;
    }

    public boolean getUseTableNameAlias() {
        return useTableNameAlias;
    }

    public void setUseTableNameAlias(boolean useTableNameAlias) {
        this.useTableNameAlias = useTableNameAlias;
    }

    public boolean isUseTableNameAlias() {
        return useTableNameAlias;
    }

    public String getServiceTargetFolder() {
        return serviceTargetFolder;
    }

    public void setServiceTargetFolder(String serviceTargetFolder) {
        this.serviceTargetFolder = serviceTargetFolder;
    }

    public String getControllerTargetFolder() {
        return controllerTargetFolder;
    }

    public void setControllerTargetFolder(String controllerTargetFolder) {
        this.controllerTargetFolder = controllerTargetFolder;
    }

    public String getJspTargetFolder() {
        return jspTargetFolder;
    }

    /**
     * 设置JSP目标目录
     * <p>
     * 自动添加前缀：src/main/webapp/WEB-INF/jsp/
     * <p>
     * 示例：设置值为"user"会生成路径：src/main/webapp/WEB-INF/jsp/user/
     *
     * @param jspTargetFolder JSP目录名称（不需要包含前缀）
     */
    public void setJspTargetFolder(String jspTargetFolder) {
//        this.jspTargetFolder = "src/main/webapp/WEB-INF/jsp/" + jspTargetFolder;
        this.jspTargetFolder =  jspTargetFolder;
    }

    public String getServiceImplName() {
        return serviceImplName;
    }

    public void setServiceImplName(String serviceImplName) {
        this.serviceImplName = serviceImplName;
    }

    public String getServiceImplPackage() {
        return serviceImplPackage;
    }

    public void setServiceImplPackage(String serviceImplPackage) {
        this.serviceImplPackage = serviceImplPackage;
    }

    public String getServiceImplTargetFolder() {
        return serviceImplTargetFolder;
    }

    public void setServiceImplTargetFolder(String serviceImplTargetFolder) {
        this.serviceImplTargetFolder = serviceImplTargetFolder;
    }

    public String getModuleName() {
        return moduleName;
    }

    public void setModuleName(String moduleName) {
        this.moduleName = moduleName;
    }

}
